package qf.index;//package com.qf.index;
//
//import cn.hutool.core.collection.ConcurrentHashSet;
//import cn.hutool.core.io.FileUtil;
//import cn.hutool.core.util.NumberUtil;
//import cn.hutool.db.Db;
//import cn.hutool.db.Entity;
//import cn.hutool.json.JSONUtil;
//import com.alibaba.fastjson.JSONObject;
//import lombok.Data;
//
//import java.io.File;
//import java.io.IOException;
//import java.nio.file.Files;
//import java.sql.SQLException;
//import java.text.SimpleDateFormat;
//import java.util.*;
//import java.util.concurrent.ConcurrentHashMap;
//
//public class xxmuSearch {
//
//    /**
//     * 按新乡医学院某老师的要求进行的检索，近3年（包含22年）内，按照影响因子排序，前50篇且IF>=10，综述不要求IF。杂志无要求。
//     * 贾新志 2025.01.17
//     */
//
//    public static void main(String[] args) throws SQLException {
//
//        String pmArticleTable = "scholar_25_01.spider_pubmed_vip_extend_0114";
//        String jourMergeTable = "scholar_25_01.basic_jour_merge";
//        String xxmuSearchScoreTable = "scholar_25_01.xxmu_search_score";
//        String xxmuFullPathTable = "dir.xxmu_fullpath_0119";
//        String fullPathTable = "dir.ncbijournalpdf_20250116_fullpath";
//        String searchSumTable = "scholar_25_01.xxmu_search_year_pmid_set";
//
//        // 2025.01.19 使用的方法1，功能是根据手工检索的结果，根据全文表中是否有全文，再获取各pmId的论文详情（含年份及影响因子等）
/// /        getPmIdAndJcrIf(xxmuSearchScoreTable, "id", "pub_year`,`article_title`,`keyword`,`ab_text`,`pts`,`med_nlm_id`,`pmid`,`jour", jourMergeTable, pmArticleTable, fullPathTable);
//
//        // 2025.01.19 使用的方法2，根据年份、影响因子以及类型（大于10或大于5），对论文进行划分，请读者区分进行核实和筛选确定需要下载的清单。
////        insertSearchSum(xxmuSearchScoreTable, "id", "search`,`year`,`pmId`,`jcr_if", searchSumTable);
//
//        // 2025.01.19 使用的方法3，经读者再三确认检索策略没错，且已选择了需要的年份，开始整理下载的fullPath。
////        idToPmIdToFullPath(searchSumTable, xxmuFullPathTable, fullPathTable);
//
//        // 根据检索词，从pmArticleTable表中把符合条件的记录插入到xxmuSearchScoreTable表中。
////        insertTable(pmArticleTable, "id", "pub_year`,`article_title`,`keyword`,`ab_text`,`pts`,`med_nlm_id`,`pmid`,`jour", xxmuSearchScoreTable, jourMergeTable);
//
//        // 全文中有的pmId号集合
////        Set<Integer> fullPmIdSet = getFullPmIdSet(fullPathTable, "pid", "fullpath");
////        insertSearchSum(xxmuSearchScoreTable, "id", "search`,`year`,`pmId", fullPmIdSet, searchSumTable);
//
//        // 从检索结果表中，先获取pmId集合，再把各pmId相对应的在服务器上路径保存到xxmuFullPathTable表中。
////        Set<String> pmIdSet = getPmIdSet(xxmuSearchScoreTable, "id", "pmId");
////        insertFullPathTable(fullPathTable, "pid", "fullpath", pmIdSet, xxmuFullPathTable);
//
//        // 2025.01.19 使用的方法4，把各个检索词当作文件夹，把该检索词下的全文，复制进去。
//        copyPdfFile(searchSumTable, "id", "search`,`pmIdSet`,`year");
//
//        // 2025.01.19 使用的方法4，把各个检索词当作文件夹，把该检索词下的全文，复制进去。
////        checkPdfFile(xxmuSearchScoreTable, "id", "search`,`pmIdSet`,`year");
//
//        /*
//          0|[["biomimetic tendon"],["fibrous","tendon regeneration"],["tenogenic","hydrogel"]]
//          1|[["atrophic nonunion","regeneration"],["Immune Regulation","bone regeneration"],["Angiogenesis","bone regeneration"],["Endochondral Ossification","bone regeneration"],["Piezoelectric","bone regeneration"]]
//          2|[["Drug screening and evaluation","organoids"],["drug resistance organ development process","organoids"]]
//          3|[["induced pluripotent stem cells","chondrocyte"]]
//          4|[["neural networks","organoids"]]
//          5|[["Tendon-bone healing"]]
//          6|[["Bone marrow organoid"]]
//          7|[["induced pluripotent stem cells","osteoarthritis"]]
//          8|[["organoids and the immune system","organoids"],["cytokines","organoids"]]
//          9|[["Setm cells","organoids"],["Optimization of culture media","organoids"],["extracellular microenvironment","organoids"]]
//          10|[["induced pluripotent stem cells","vascularization"]]
//          11|[["induced pluripotent stem cells","bone regeneration"]]
//          12|[["induced pluripotent stem cells","mesenchymal stem cell"]]
//          13|[["induced pluripotent stem cells","cartilage regeneration"]]
//          14|[["Joint Replacement","regeneration"]]
//          15|[["induced pluripotent stem cells","osteoblast"]]
//          16|[["cartilage regeneration"]]
//          17|[["induced pluripotent stem cells","neural network"]]
//         */
//
//    }
//
//    public static void checkPdfFile(String xxmuSearchScoreTable, String autoId, String field) throws SQLException {
//        List<File> files = FileUtil.loopFiles("F:\\xxmu\\result");
//        // F:\xxmu\result\n9_神经网络\2024\miR126 mediated impaired vascular in [PMIDG39415995].pdf
//        Map<String, List<String>> searchYearAndFileListMap = new HashMap<>();
//        Set<String> pmIdSet = new HashSet<>();
//        for (File file : files) {
//            String filePath = file.getAbsolutePath();
//            String[] split = filePath.split("\\\\");
//            if (split.length > 5) {
////                System.out.println(split[3] + "--" + split[4]);
//                putStrListStr(searchYearAndFileListMap, split[3] + "|" + split[4], filePath);
//                String fileId = Utils.getFileId(filePath);
//                pmIdSet.add(fileId);
//            }
//
//        }
//        for (Map.Entry<String, List<String>> entry : searchYearAndFileListMap.entrySet()) {
////            System.out.println(entry.getKey() + "|" + entry.getValue().size());
//        }
//
//        Map<String, Integer> searchYearAndSumMap = new HashMap<>();
//        Set<Integer> idSet = new HashSet<>();
//        String ids = "230,231,232,189,190,141,142,143,1468,1469,1470,10,11,1327,1328,1329,306,307,308,1032,1033,1034,335,336,337,233,234,235,1420,191,192,193,144,145,146,1471,1472,1473,12,13,1330,1331,1332,309,310,311," +
//                "1035,1036,1037,338,339,340,236,237,238,1421,194,195,196,147,148,149,1474,1475,1476,14,15,16,1053,1333,1334,1335,312,313,314,1038,1039,1040,341,342,343,239,240,241,1422,197,198,199,150,151,152,1477,1478,1479," +
//                "17,18,19,1336,1337,1338,315,316,317,1041,1042,1043,344,345,346,242,243,244,1423,200,201,202,153,154,155,1480,1481,20,21,22,1339,1340,318,319,320,1044,1045,1046,347,348,349,245,246,247,203,204,205,156,157," +
//                "158,1482,1483,23,24,25,1341,1342,1343,321,322,323,1047,1048,1049,350,351,352,248,26,1050,1051,1083,1084,1085,165,166,167,84,1260,1261,1262,1373,1374,1375,947,948,949,1289,1290,1291,873,874,875,703,704,705," +
//                "833,834,835,1394,1395,1086,1087,1088,168,169,170,85,86,1263,1264,1265,1376,1377,1378,950,951,952,1292,1293,1294,876,877,878,706,707,708,836,837,1396,1089,1090,1091,171,172,173,87,1266,1267,1268,1379,1380," +
//                "1381,953,954,955,1296,1297,1298,879,880,881,709,710,711,838,839,840,1397,1398,1399,1092,1093,1094,174,175,176,88,89,90,1269,1270,1271,1382,1383,1384,956,957,958,1299,1300,1301,883,884,885,712,713,714,841," +
//                "842,843,1400,1401,1095,1096,177,1272,1273,959,960,961,1302,1303,1304,887,888,889,715,716,717,421,422,423,69,70,71,482,483,1155,1156,655,656,657,797,798,799,580,581,424,425,426,72,73,484,485,486,1157,1158," +
//                "1159,658,659,660,800,801,802,582,427,428,429,74,75,76,487,488,489,1160,1161,661,662,663,803,804,805,583,584,585,430,431,432,77,78,79,490,491,492,1162,1163,664,665,666,806,807,808,586,587,433,434,435,1164,667,668,669,809,810";
//        String[] split = ids.split(",");
//        for (String s : split) {
//            if (NumberUtil.isInteger(s)) {
//                idSet.add(Integer.parseInt(s));
//            }
//        }
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + xxmuSearchScoreTable);
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + xxmuSearchScoreTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            for (Integer startId : tableList) {
//                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + xxmuSearchScoreTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                for (Entity entry : tableData) {
//                    String search = entry.getStr("search");
//                    Integer id = entry.getInt(autoId);
//                    Integer year = entry.getInt("year");
//                    String pmIds = entry.getStr("pmIdSet");
//                    if (null != search && !search.isEmpty() && null != pmIds && pmIds.contains("]") && null != id && idSet.contains(id) && null != year) {
//                        List<String> pmIdList = JSONObject.parseArray(pmIds, String.class);
//                        searchYearAndSumMap.compute(search + "|" + year, (key, value) -> value != null ? (value + pmIdList.size()) : pmIdList.size());
//                        for (String s : pmIdList) {
//                            if (!pmIdSet.contains("PM" + s)) {
//                                System.out.println("本地硬盘上没有的： " + s);
//                            }
//                        }
//                    }
//                }
//            }
//        }
//
//        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//        for (Map.Entry<String, Integer> entry : searchYearAndSumMap.entrySet()) {
////            System.out.println(entry.getKey() + "|" + entry.getValue());
//        }
//
//
//    }
//
//    public static void putStrListStr(Map<String, List<String>> strListStrMap, String name, String list) {
//        strListStrMap.compute(name, (k, v) -> {
//            if (v == null) {
//                v = Collections.synchronizedList(new ArrayList<String>());
//            }
//            v.add(list);
//            return v;
//        });
//    }
//
//
//    public static void copyPdfFile(String xxmuSearchScoreTable, String autoId, String field) throws SQLException {
//        Set<Integer> idSet = new HashSet<>();
//        String ids = "80,173,174,175,77,78,79,170,171,172,74,75,76,167,168,169,72,73,164,165,166,69,70,71,161,162";
//        String[] split = ids.split(",");
//        for (String s : split) {
//            if (NumberUtil.isInteger(s)) {
//                idSet.add(Integer.parseInt(s));
//            }
//        }
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + xxmuSearchScoreTable);
//        Map<String, Map<Integer, Set<Integer>>> searchAndPmIdSetMap = new HashMap<>();
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + xxmuSearchScoreTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            for (Integer startId : tableList) {
//                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + xxmuSearchScoreTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                for (Entity entry : tableData) {
//                    String search = entry.getStr("search");
//                    Integer id = entry.getInt(autoId);
//                    Integer year = entry.getInt("year");
//                    String pmIds = entry.getStr("pmIdSet");
//                    if (null != search && !search.isEmpty() && null != pmIds && pmIds.contains("]") && null != id && idSet.contains(id) && null != year) {
//                        List<String> pmIdList = JSONObject.parseArray(pmIds, String.class);
//                        for (String pmId : pmIdList) {
//                            if (NumberUtil.isInteger(pmId)) {
//                                putStrIntSetInt(searchAndPmIdSetMap, search, year, Integer.parseInt(pmId));
//                            }
//                        }
//                    }
//                }
//            }
//        }
//        Map<Integer, String> pmIdAndFilePathMap = new HashMap<>();
//        List<File> files = FileUtil.loopFiles("C:\\临时文件\\2024_12\\XXMU\\0123\\tmp2\\sas\\tmp2");
//        for (File file : files) {
//            String filePath = file.getAbsolutePath();
//            String fileId = Utils.getFileId(filePath);
//            if (fileId.startsWith("PM")) {
//                pmIdAndFilePathMap.put(Integer.parseInt(fileId.substring(2)), filePath);
//            }
//        }
//
//        for (Map.Entry<String, Map<Integer, Set<Integer>>> entry : searchAndPmIdSetMap.entrySet()) {
//            String search = entry.getKey();
//            Map<Integer, Set<Integer>> value = entry.getValue();
//            for (Map.Entry<Integer, Set<Integer>> map : value.entrySet()) {
//                Integer year = map.getKey();
//                Set<Integer> pmIdSet = map.getValue();
//                for (Integer pmId : pmIdSet) {
//                    if (pmIdAndFilePathMap.containsKey(pmId)) {
//                        copyFile(pmIdAndFilePathMap.get(pmId), "C:\\临时文件\\2024_12\\XXMU\\0123\\tmp2\\sas\\tmp2\\" + search + "\\" + year, "");
//                    }
//                }
//            }
//        }
//
//    }
//
//    public static void putStrIntSetInt(Map<String, Map<Integer, Set<Integer>>> unitAuthAidMap, String mail, int auth_id, int aId) {
//        if (!mail.isEmpty() && auth_id > 0 && aId > 0) {
//            unitAuthAidMap.compute(mail, (k, v) -> {
//                if (v == null) {
//                    v = new ConcurrentHashMap<>();
//                }
//                v.compute(auth_id, (k1, v1) -> {
//                    if (v1 == null) {
//                        v1 = new ConcurrentHashSet<>();
//                    }
//                    v1.add(aId);
//                    return v1;
//                });
//                return v;
//            });
//        }
//    }
//
////    public static void putStrIntSetInt(Map<String, Map<Integer, Set<Integer>>> unitAuthAidMap, String mail, int auth_id, int aId) {
////        if (mail.length() > 0 && auth_id > 0 && aId > 0) {
////            unitAuthAidMap.compute(mail, (k, v) -> {
////                if (v == null) {
////                    v = new ConcurrentHashMap<>();
////                }
////                v.compute(auth_id, (k1, v1) -> {
////                    if (v1 == null) {
////                        v1 = new ConcurrentHashSet<>();
////                    }
////                    v1.add(aId);
////                    return v1;
////                });
////                return v;
////            });
////        }
////    }
//
//    public static void idToPmIdToFullPath(String searchSumTable, String xxmuFullPathTable, String fullPathTable) throws SQLException {
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        Set<Integer> idSet = new HashSet<>();
//        String ids = "80,173,174,175,77,78,79,170,171,172,74,75,76,167,168,169,72,73,164,165,166,69,70,71,161,162";
//        String[] split = ids.split(",");
//        for (String s : split) {
//            if (NumberUtil.isInteger(s)) {
//                idSet.add(Integer.parseInt(s));
//            }
//        }
//        System.out.println("idSet.size(): " + idSet.size());
//        String autoId = "id";
//        String field = "pmIdSet";
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + searchSumTable);
//        Set<String> pmIdSet = new HashSet<>();
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + searchSumTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            for (Integer startId : tableList) {
//                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + searchSumTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + searchSumTable + Utils.printMemoryStr() + "\033[0m");
//                for (Entity entry : tableData) {
//                    Integer id = entry.getInt(autoId);
//                    if (idSet.contains(id)) {
//                        String pmIds = entry.getStr("pmIdSet");
//                        if (null != pmIds && pmIds.contains("]")) {
//                            List<String> pmIdList = JSONObject.parseArray(pmIds, String.class);
//                            for (String pmId : pmIdList) {
//                                if (NumberUtil.isInteger(pmId)) {
//                                    pmIdSet.add("PM" + pmId);
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//        }
//        //"pid", "fullpath"
//        autoId = "pid";
//        field = "fullpath";
//        insertFullPathTable(fullPathTable, autoId, field, pmIdSet, xxmuFullPathTable);
//    }
//
//    public static void getPmIdAndJcrIf(String xxmuSearchScoreTable, String autoId, String field, String jourMergeTable, String pmArticleTable, String fullPathTable) throws SQLException {
//        // 获取各nlmId相对应的jcr影响因子。
//        Map<String, Double> nlmIdAndJcrIfMap = getNlmIdAndJcrIfMap(jourMergeTable, "id", "nc_nlmid_list`,`jcr_if");
//        Set<Integer> fullPmIdSet = getFullPmIdSet(fullPathTable, "pid", "fullpath");
//        List<File> files = FileUtil.loopFiles("C:\\临时文件\\2024_12\\XXMU\\0123");
//        Map<Integer, Set<String>> pmIdAndSubjectSetMap = new HashMap<>();
//        for (File file : files) {
//            String filePath = file.getAbsolutePath();
//            List<String> list = FileUtil.readLines(filePath, "utf-8");
//            String subject = filePath.substring("C:\\临时文件\\2024_12\\XXMU\\0123\\".length(), filePath.length() - ".txt".length());
//            for (String s : list) {
//                if (NumberUtil.isInteger(s)) {
//                    int pmId = Integer.parseInt(s);
//                    if (fullPmIdSet.contains(pmId)) {
//                        putIntSetStr(Integer.parseInt(s), subject, pmIdAndSubjectSetMap);
//                    }
//                }
//            }
//        }
//
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + pmArticleTable);
//        String s = "<p> <strong class=\"sub-title\"> Keywords: </strong>";
//        Db.use().execute("truncate table " + xxmuSearchScoreTable);
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + pmArticleTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            tableList.parallelStream().forEach(startId -> {
//                try {
//                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + pmArticleTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                    for (Entity entry : tableData) {
//                        int pmId = Utils.getIntField(entry, "pmid");
//                        if (pmIdAndSubjectSetMap.containsKey(pmId)) {
//                            String pubYear = entry.getStr("pub_year");
//                            int year = (null != pubYear && pubYear.trim().length() == 4 && NumberUtil.isInteger(pubYear.trim())) ? Integer.parseInt(pubYear.trim()) : 1900;
//                            String title = Utils.getStrField(entry, "article_title");
//                            String keyword = Utils.getStrField(entry, "keyword");
//                            keyword = keyword.startsWith(s) && keyword.endsWith("</p>") ? keyword.substring(s.length(), keyword.length() - "</p>".length()) : keyword;
//                            String abText = Utils.getStrField(entry, "ab_text");
//                            abText = abText.endsWith("</p>") ? abText.substring(0, abText.length() - "</p>".length()).trim() : abText;
//                            abText = abText.startsWith("<p>") ? abText.substring("<p>".length()).trim() : abText;
//                            abText = abText.replace("<strong class=\"sub-title\">", " ").replace(" </strong>", " ").replace("</p><p>", " ").replaceAll(" +", " ").trim();
//                            Set<String> ptSet = getPtSet(entry.getStr("pts"));
//                            // 是否为综述
//                            boolean isReview = ptSet.contains("Review");
//                            String medNlmId = Utils.getStrField(entry, "med_nlm_id");
//                            String jour = Utils.getStrField(entry, "jour");
//                            Set<String> subjectSet = pmIdAndSubjectSetMap.get(pmId);
//                            Double jcrIf = nlmIdAndJcrIfMap.getOrDefault(medNlmId, 0.0);
//                            for (String subject : subjectSet) {
//                                try {
//                                    Db.use().insert(Entity.create(xxmuSearchScoreTable).set("search", subject).set("pmId", pmId).set("jcr_if", jcrIf).set("year", year).set("ti", title).set("kw", keyword.trim())
//                                            .set("ab", abText).set("pt", JSONUtil.toJsonStr(ptSet)).set("is_review", isReview ? 1 : 0).set("jour", jour));
//                                } catch (SQLException e) {
//                                    e.printStackTrace();
//                                }
//                            }
//                        }
//                    }
//                } catch (SQLException e) {
////                    throw new RuntimeException(e);
//                }
//            });
//        }
//    }
//
//    public static void putIntSetStr(Integer id, String str, Map<Integer, Set<String>> intSetStrMap) {
//        if (id > 0 && !str.isEmpty()) {
//            intSetStrMap.compute(id, (k, v) -> {
//                if (v == null) {
//                    v = new ConcurrentHashSet<>();
//                }
//                v.add(str);
//                return v;
//            });
//        }
//    }
//
//    public static void insertSearchSum(String xxmuSearchScoreTable, String autoId, String field, String searchSumTable) throws SQLException {
//        String str = "半月板|\"Meniscus Regeneration\" OR \"Meniscus Tears\"\n" +
//                "椎间盘|\"Intervertebral disc degeneration\"[TIAB] OR \"Intervertebral disc regeneration\"[TIAB]";
//        String[] split = str.split("\n");
//        Map<String, String> searchAndWordMap = new HashMap<>();
//        for (String s : split) {
//            if (s.contains("|")) {
//                String[] list = s.split("\\|");
//                if (list.length == 2) {
//                    searchAndWordMap.put(list[0], list[1]);
//                }
//            }
//        }
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + xxmuSearchScoreTable);
//        Map<String, Map<Integer, Map<String, Set<Integer>>>> searchYearTypePmIdSetMap = new HashMap<>();
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + xxmuSearchScoreTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            for (Integer startId : tableList) {
//                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + xxmuSearchScoreTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + xxmuSearchScoreTable + Utils.printMemoryStr() + "\033[0m");
//                for (Entity entry : tableData) {
//                    String search = entry.getStr("search");
//                    Integer year = entry.getInt("year");
//                    Integer pmId = entry.getInt("pmId");
//                    Double jcrIf = entry.getDouble("jcr_if");
//                    String type = "dy0.0";
//                    type = jcrIf > 5.0 ? "dy5.0" : type;
//                    type = jcrIf > 10.0 ? "dy10.0" : type;
//                    putEnCnAuInfoAidMap(searchYearTypePmIdSetMap, search, year, type, pmId);
//                }
//            }
//        }
//        Db.use().execute("truncate table " + searchSumTable);
//        for (Map.Entry<String, Map<Integer, Map<String, Set<Integer>>>> entry : searchYearTypePmIdSetMap.entrySet()) {
//            String search = entry.getKey();
//            String word = searchAndWordMap.getOrDefault(search, "");
//            Map<Integer, Map<String, Set<Integer>>> yearTypePmIdSetMap = entry.getValue();
//            for (Map.Entry<Integer, Map<String, Set<Integer>>> map : yearTypePmIdSetMap.entrySet()) {
//                Integer year = map.getKey();
//                Map<String, Set<Integer>> typePmIdSetMap = map.getValue();
//                for (Map.Entry<String, Set<Integer>> entity : typePmIdSetMap.entrySet()) {
//                    String type = entity.getKey();
//                    Set<Integer> pmIdSet = entity.getValue();
//                    try {
//                        Db.use().insert(Entity.create(searchSumTable).set("search", search).set("word", word).set("type", type).set("year", year).set("pmIdSet", JSONUtil.toJsonStr(pmIdSet)).set("sum", pmIdSet.size()));
//                    } catch (SQLException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }
//    }
//
//    public static void putEnCnAuInfoAidMap(Map<String, Map<Integer, Map<String, Set<Integer>>>> enCnAuInfoAidMap, String search, Integer year, String type, int pmId) {
//        // Map<String, Map<Integer, Map<String, Set<Integer>>>> searchAndYearAndPmIdSetMap = new HashMap<>();
//        enCnAuInfoAidMap.compute(search, (k, v) -> {
//            if (v == null) {
//                v = new ConcurrentHashMap<>();
//            }
//            v.compute(year, (k1, v1) -> {
//                if (v1 == null) {
//                    v1 = new ConcurrentHashMap<>();
//                }
//                v1.compute(type, (k2, v2) -> {
//                    if (v2 == null) {
//                        v2 = new ConcurrentHashSet<>();
//                    }
//                    v2.add(pmId);
//                    return v2;
//                });
//                return v1;
//            });
//            return v;
//        });
//    }
//
//
//    public static void insertTable(String pmArticleTable, String autoId, String field, String xxmuSearchScoreTable, String jourMergeTable) throws SQLException {
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        // 以下共7组检索词，每组内的各检索词是 OR 的关系，即任一符合要求即可。
//        List<List<List<String>>> searchList = new ArrayList<>();
//        searchList.add(addList("biomimetic tendon; fibrous+tendon regeneration; tenogenic+hydrogel"));
//        searchList.add(addList("Tendon-bone healing"));
//        searchList.add(addList("Osteochondral generation"));
//        searchList.add(addList("Joint Replacement+regeneration"));
//        searchList.add(addList("atrophic nonunion+regeneration; Immune Regulation+bone regeneration; Angiogenesis+bone regeneration; Endochondral Ossification+bone regeneration; Piezoelectric+bone regeneration"));
//        searchList.add(addList("cartilage regeneration"));
//        searchList.add(addList("Femoral Head Regeneration"));
//        searchList.add(addList("Setm cells+organoids; Optimization of culture media+organoids; extracellular microenvironment+organoids"));
//        searchList.add(addList("Formation of vascularization+organoids"));
//        searchList.add(addList("neural networks+organoids"));
//        searchList.add(addList("Modeling of genetic diseases+organoids; bone tumor+organoids"));
//        searchList.add(addList("Drug screening and evaluation+organoids; drug resistance organ development process+organoids"));
//        searchList.add(addList("organoids and the immune system+organoids; cytokines+organoids"));
//        searchList.add(addList("Bone marrow organoid"));
//        searchList.add(addList("Osteoblasts organoid; Osteoclasts organoid; Osteoarthritis organoid; Osteosarcoma organoid; Femur Head Necrosis organoid"));
//        searchList.add(addList("induced pluripotent stem cells+mesenchymal stem cell"));
//        searchList.add(addList("induced pluripotent stem cells+chondrocyte"));
//        searchList.add(addList("induced pluripotent stem cells+osteoblast"));
//        searchList.add(addList("induced pluripotent stem cells+osteoarthritis"));
//        searchList.add(addList("induced pluripotent stem cells+femoral head regeneration"));
//        searchList.add(addList("induced pluripotent stem cells+cartilage regeneration"));
//        searchList.add(addList("induced pluripotent stem cells+bone regeneration"));
//        searchList.add(addList("induced pluripotent stem cells+vascularization"));
//        searchList.add(addList("induced pluripotent stem cells+neural network"));
//        searchList.add(addList("induced pluripotent stem cells+inflammation+osteoarthritis"));
//        searchList.add(addList("induced pluripotent stem cells+inflammation+bone"));
//        // 获取各nlmId相对应的jcr影响因子。
//        Map<String, Double> nlmIdAndJcrIfMap = getNlmIdAndJcrIfMap(jourMergeTable, "id", "nc_nlmid_list`,`jcr_if");
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + pmArticleTable);
//        String s = "<p> <strong class=\"sub-title\"> Keywords: </strong>";
//        Db.use().execute("truncate table " + xxmuSearchScoreTable);
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + pmArticleTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            tableList.parallelStream().forEach(startId -> {
//                try {
//                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + pmArticleTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                    System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + pmArticleTable + Utils.printMemoryStr() + "\033[0m");
//                    for (Entity entry : tableData) {
//                        String pubYear = entry.getStr("pub_year");
//                        int year = (null != pubYear && pubYear.trim().length() == 4 && NumberUtil.isInteger(pubYear.trim())) ? Integer.parseInt(pubYear.trim()) : 1900;
//                        if (year >= 1900) {
//                            for (List<List<String>> wordsList : searchList) {
//                                String title = Utils.getStrField(entry, "article_title");
//                                // 标题是否符合检索条件。
//                                boolean isTi = isContains(title, wordsList);
//                                String keyword = Utils.getStrField(entry, "keyword");
//                                keyword = keyword.startsWith(s) && keyword.endsWith("</p>") ? keyword.substring(s.length(), keyword.length() - "</p>".length()) : keyword;
//                                // 关键词是否符合检索条件。
//                                boolean isKw = isContains(keyword, wordsList);
////                                boolean isAb = false;
//                                // 摘要是否符合检索条件，说明，摘要中是按句子来拆分的，任一句符合即按符合计算。
//                                String abText = Utils.getStrField(entry, "ab_text");
//                                abText = abText.endsWith("</p>") ? abText.substring(0, abText.length() - "</p>".length()).trim() : abText;
//                                abText = abText.startsWith("<p>") ? abText.substring("<p>".length()).trim() : abText;
//                                abText = abText.replace("<strong class=\"sub-title\">", " ").replace(" </strong>", " ").replace("</p><p>", " ").replaceAll(" +", " ").trim();
//                                boolean isAb = isContains(abText, wordsList);
////                                String[] split = abText.split("\\. ");
////                                for (String str : split) {
////                                    if (isContains(str, wordsList)) {
////                                        isAb = true;
////                                        break;
////                                    }
////                                }
//                                if (isTi || isKw || isAb) {
//                                    // 获取文献类型
//                                    Set<String> ptSet = getPtSet(entry.getStr("pts"));
//                                    // 是否为综述
//                                    boolean isReview = ptSet.contains("Review");
//                                    String medNlmId = Utils.getStrField(entry, "med_nlm_id");
//                                    String jour = Utils.getStrField(entry, "jour");
//                                    int pmId = Utils.getIntField(entry, "pmid");
//                                    // 得分体系，如果标题、关键词、摘要中含有检索词，系数为最高，如果是综述再乘以1.5倍，最后再乘以影响因子作为总得分。
//                                    double score = 0.0;
//                                    score = isAb ? 0.2 : score;
//                                    score = isKw ? 0.4 : score;
//                                    score = isTi ? 0.5 : score;
//                                    score = isKw && isAb ? 0.6 : score;
//                                    score = isTi && isAb ? 0.7 : score;
//                                    score = isTi && isKw ? 0.9 : score;
//                                    score = isTi && isKw && isAb ? 1.0 : score;
//                                    score = isReview ? score * 1.5 : score;
//                                    Double jcrIf = nlmIdAndJcrIfMap.getOrDefault(medNlmId, 0.0);
//                                    try {
//                                        Db.use().insert(Entity.create(xxmuSearchScoreTable).set("search", JSONUtil.toJsonStr(wordsList)).set("pmId", pmId).set("jcr_if", jcrIf).set("year", year).set("ti", title).set("kw", keyword.trim()).set("ab", abText).set("pt", JSONUtil.toJsonStr(ptSet))
//                                                .set("is_ti", isTi ? 1 : 0).set("is_ab", isAb ? 1 : 0).set("is_kw", isKw ? 1 : 0).set("is_review", isReview ? 1 : 0).set("score", Utils.takeFourDigits(jcrIf * score)).set("jour", jour));
//                                    } catch (SQLException e) {
//                                        e.printStackTrace();
//                                    }
//                                }
//                            }
//                        }
//                    }
//                } catch (SQLException e) {
////                    throw new RuntimeException(e);
//                }
//            });
//        }
//    }
//
//    public static List<List<String>> addList(String search) {
//        // 按用户指定的检索词，转换为list格式，因检索词最多只有两节（以"+"来区分），所以，分为了ab两个词。
//        List<List<String>> wordsList = new ArrayList<>();
//        String[] split = search.split("; ");
//        for (String s : split) {
//            String[] words = s.split("\\+");
//            List<String> list = new ArrayList<>(Arrays.asList(words));
//            wordsList.add(list);
//        }
//        return wordsList;
//    }
//
//    public static Set<String> getPtSet(String pts) {
//        // 获取文献类型的集合
//        List<PubType> pubTypes = JSONObject.parseArray((null == pts || pts.isEmpty()) ? "[]" : pts, PubType.class);
//        Set<String> ptSet = new HashSet<>();
//        for (PubType pubType : pubTypes) {
//            String typeTitle = pubType.getTitle().trim();
//            if (!typeTitle.isEmpty()) {
//                ptSet.add(typeTitle);
//            }
//        }
//        return ptSet;
//    }
//
//    @Data
//    public static class PubType {
//        private List<Href> hrefs = new ArrayList<>();
//        private String title = "";
//        private int type = 0;
//    }
//
//    @Data
//    public static class Href {
//        private String name = "";
//        private String href = "";
//    }
//
//    public static boolean isContains(String title, List<List<String>> wordsList) {
//        // 本程序的核心，检索逻辑部分，本组检索词中，任一组内的检索词，如果标题或关键词或摘要中的句子任一包含，即为符合检索条件。
//        if (null != title) {
//            title = title.toLowerCase().trim();
//            for (List<String> words : wordsList) {
//                boolean bool = true;
//                for (String word : words) {
//                    if (!title.contains(word.toLowerCase().trim())) {
//                        bool = false;
//                        break;
//                    }
//                }
//                if (bool) {
//                    return true;
//                }
//            }
//        }
//        return false;
//    }
//
//    public static Map<String, Double> getNlmIdAndJcrIfMap(String jourMergeTable, String autoId, String field) throws SQLException {
//        // 获取影响因子
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + jourMergeTable);
//        Map<String, Double> nlmIdAndJcrIfMap = new HashMap<>();
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + jourMergeTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            for (Integer startId : tableList) {
//                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + jourMergeTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                for (Entity entry : tableData) {
//                    String ncNlmids = entry.getStr("nc_nlmid_list");
//                    Double jcrIf = entry.getDouble("jcr_if");
//                    if (null != ncNlmids && null != jcrIf && ncNlmids.contains("\"]") && jcrIf > 0.0) {
//                        List<String> ncNlmidList = JSONObject.parseArray(ncNlmids, String.class);
//                        for (String nlmId : ncNlmidList) {
//                            nlmIdAndJcrIfMap.put(nlmId.toUpperCase(), jcrIf);
//                        }
//                    }
//                }
//            }
//        }
//        return nlmIdAndJcrIfMap;
//    }
//
//
//    // 复制文件。比如来源文件source:E:\\dir_47p_0512.txt  指定目录newPath:E:\\51P，若newFileName新文件名为空，仍是原来的文件名字，若有新文件名，则保存为新的文件名。
//    // copyFile("G:\\lh_2023_12_21\\郜冰洁\\6月\\6.11-6.16\\已上传\\Sciatica [PMIDM29821100].pdf","H:\\S201791LH\\2023-10-1\\","Sciatica Source Hospital Lond 1886 1891 Feb 14 9 229 303[PMIDT29821100].PDF");
//    // copy("G:\\lh_2023_12_21\\以前同事\\seven\\二月\\2.18\\已上传\\1.pdf", "F:\\lh_2023_12_21\\以前同事\\seven\\二月\\2.18\\已上传",""); 这样可以在指定的位置新建相对应的文件目录，但仍是原来的文件名字
//    // String newPath = "E:\\gDiskPdf\\" + source.substring("G:\\".length(), source.lastIndexOf("\\"));
//    public static void copyFile(String source, String newPath, String newFileName) {
//        File oldFile = new File(source);
//        String fileName = source.substring(source.lastIndexOf("\\") + 1);
//        // 如果指定的目录不存在，则先给予创建
//        File directory = new File(newPath);
//        if (!directory.exists()) {
//            directory.mkdirs();
//        }
//        // 如果新的目录最后是以"\\"结尾，就不需要再添加了，如果不是，则添加上目录与文件之间的"\\"分隔符。
//        String split = newPath.endsWith("\\") ? "" : "\\";
//        File newFile = new File(newPath + split + (newFileName.length() > 1 ? newFileName : fileName));
//        // 如果目录中已存在该文件，则将已存在的给予删除，再执行复制。
//        if (newFile.exists()) {
//            newFile.delete();
//        }
//        try {
//            Files.copy(oldFile.toPath(), newFile.toPath());
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    public static void insertFullPathTable(String fullPathTable, String autoId, String field, Set<String> pmIdSet, String xxmuFullPathTable) throws SQLException {
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + fullPathTable);
//        Set<String> set = new HashSet<>();
//        Db.use().execute("truncate table " + xxmuFullPathTable);
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + fullPathTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            tableList.parallelStream().forEach(startId -> {
//                try {
//                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + fullPathTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                    System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + fullPathTable + Utils.printMemoryStr() + "\033[0m");
//                    for (Entity entry : tableData) {
//                        String fullpath = entry.getStr("fullpath");
//                        String fileId = Utils.getFileId(fullpath);
//                        if (pmIdSet.contains(fileId) && !set.contains(fileId)) {
//                            try {
//                                Db.use().insert(Entity.create(xxmuFullPathTable).set("pmId", fileId.substring(2)).set("fullpath", fullpath));
//                            } catch (SQLException e) {
//                                e.printStackTrace();
//                            }
//                            set.add(fileId);
//                        }
//                    }
//                } catch (SQLException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//        }
//    }
//
//    public static Set<Integer> getFullPmIdSet(String fullPathTable, String autoId, String field) throws SQLException {
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + fullPathTable);
//        Set<Integer> pmIdSet = new ConcurrentHashSet<>();
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + fullPathTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            tableList.parallelStream().forEach(startId -> {
//                try {
//                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + fullPathTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                    for (Entity entry : tableData) {
//                        String fileId = Utils.getFileId(entry.getStr("fullpath"));
//                        if (fileId.startsWith("PM")) {
//                            pmIdSet.add(Integer.parseInt(fileId.substring(2)));
//                        }
//                    }
//                } catch (SQLException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//        }
//        return pmIdSet;
//    }
//
//    public static Set<String> getPmIdSet(String xxmuSearchScoreTable, String autoId, String field) throws SQLException {
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        int onePageNum = 1000;
//        List<Entity> tableNum = Db.use().query("select count(1) as count from " + xxmuSearchScoreTable);
//        Set<String> pmIdSet = new HashSet<>();
//        if (tableNum.get(0).getInt("count") > 0) {
//            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + xxmuSearchScoreTable).intValue();
//            Collection<Integer> tableList = new ArrayList<>();
//            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
//            for (Integer startId : tableList) {
//                List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + xxmuSearchScoreTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
//                System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + xxmuSearchScoreTable + Utils.printMemoryStr() + "\033[0m");
//                for (Entity entry : tableData) {
//                    Integer pmId = entry.getInt("pmId");
//                    if (null != pmId && pmId > 0) {
//                        pmIdSet.add("PM" + pmId);
//                    }
//                }
//            }
//        }
//        return pmIdSet;
//    }
//
//
//}
